package aquactl.views;

import java.lang.reflect.InvocationTargetException;
import java.util.Set;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;

import aquactl.Application;
import aquactl.comapi.ComException;
import aquactl.comapi.objects.Timer;

public class TimerView extends ViewPart {
	public static final String ID = "aquactl.views.TimerView";

	public static final int MAX_TIMER_SIZE = 8;

	private static final int MAX_TIMER_INFO = 4;

	private Text[] timerInput = new Text[MAX_TIMER_SIZE * MAX_TIMER_INFO];
	private Group[] timerGroup = new Group[MAX_TIMER_SIZE];
	private Button[] powerStatusInput = new Button[MAX_TIMER_SIZE];
	private Button[] timerStatusInput = new Button[MAX_TIMER_SIZE];

	private Text text;

	private Action updateTimersAction;

	private void updateTimers() {
		ProgressMonitorDialog dialog = new ProgressMonitorDialog(Display
				.getCurrent().getActiveShell());
		dialog.setCancelable(false);
		try {
			dialog.run(true, false, new IRunnableWithProgress() {
				public void run(IProgressMonitor monitor) {
					monitor.beginTask("Communicating with COM port ...", 100);
					final Set<Timer> timers;
					try {
						timers = Application.getComApi().readTimers();
					} catch (ComException e) {
						MessageDialog.openError(getSite().getShell(),
								"Comunication errror", e.getMessage());
						return;
					}
					Display.getDefault().asyncExec(new Runnable() {

						@Override
						public void run() {
							for (Timer timer : timers) {
								if (timer.isActive()) {
									timerInput[timer.getId() * MAX_TIMER_INFO]
											.setText(timer.getHourOn());
									timerInput[timer.getId() * MAX_TIMER_INFO
											+ 1].setText(timer.getMinuteOn());
									timerInput[timer.getId() * MAX_TIMER_INFO
											+ 2].setText(timer.getHourOff());
									timerInput[timer.getId() * MAX_TIMER_INFO
											+ 3].setText(timer.getMinuteOff());
								} else {
									timerInput[timer.getId() * MAX_TIMER_INFO]
											.setText("12");
									timerInput[timer.getId() * MAX_TIMER_INFO
											+ 1].setText("00");
									timerInput[timer.getId() * MAX_TIMER_INFO
											+ 2].setText("12");
									timerInput[timer.getId() * MAX_TIMER_INFO
											+ 3].setText("00");

								}
								powerStatusInput[timer.getId()]
										.setSelection(timer.isOn());
								timerStatusInput[timer.getId()]
										.setSelection(timer.isActive());
							}
						}
					});
					monitor.done();
				}
			});
		} catch (InvocationTargetException e) {
			// ignore
		} catch (InterruptedException e) {
			// ignore
		}
	}

	private void transferTimers() throws ComException {
		ProgressMonitorDialog dialog = new ProgressMonitorDialog(Display
				.getCurrent().getActiveShell());
		dialog.setCancelable(false);
		try {
			dialog.run(true, false, new IRunnableWithProgress() {
				public void run(final IProgressMonitor monitor) {
					try {
						monitor.beginTask("Communicating with COM port", 8);
						final Set<Timer> timers = Application.getComApi()
								.readTimers();
						monitor.beginTask("Sending timers", timers.size());
						Display.getDefault().asyncExec(new Runnable() {
							@Override
							public void run() {
								int i = 0;
								for (Timer timer : timers) {
									timer.setHourOn(timerInput[timer.getId()
											* MAX_TIMER_INFO].getText());
									timer.setMinuteOn(timerInput[timer.getId()
											* MAX_TIMER_INFO + 1].getText());
									timer.setHourOff(timerInput[timer.getId()
											* MAX_TIMER_INFO + 2].getText());
									timer.setMinuteOff(timerInput[timer.getId()
											* MAX_TIMER_INFO + 3].getText());
									timer.setOn(powerStatusInput[timer.getId()]
											.getSelection());
									timer.setActive(timerStatusInput[timer
											.getId()].getSelection());
									try {
										Application.getComApi().writeTimer(
												timer);
									} catch (ComException ex) {
										MessageDialog.openError(getSite()
												.getShell(),
												"Comunication errror", ex
														.getMessage());
									}
									monitor.worked(++i);
								}
							}
						});
					} catch (ComException ex) {
						MessageDialog.openError(getSite().getShell(),
								"Comunication errror", ex.getMessage());
					}
					monitor.done();
				}
			});
		} catch (InvocationTargetException exe) {
			// ignore
		} catch (InterruptedException exe) {
			// ignore
		}
	}

	private String getName(int id) {
		switch (id) {
		default:
			return "Timer " + id;
		case 0:
			return "HQI L";
		case 1:
			return "HQI R";
		case 2:
			return "T5 1";
		case 3:
			return "T5 2";
		case 4:
			return "Wiatrak lampy";
		case 5:
			return "Odpieniacz";
		case 6:
			return "Cyrkulacja 1";
		case 7:
			return "Cyrkulacja 2";
		}
	}

	private void initView(Composite parent) {
		GridLayout gridLayout = new GridLayout();
		gridLayout.numColumns = 4;
		gridLayout.makeColumnsEqualWidth = true;
		parent.setLayout(gridLayout);
		
		for (int i = 0; i < MAX_TIMER_SIZE; i++) {
			Group group = new Group(parent, SWT.SHADOW_ETCHED_IN);
			group.setText(getName(i));
			gridLayout = new GridLayout();
			gridLayout.numColumns = 4;
			gridLayout.makeColumnsEqualWidth = false;
			group.setLayout(gridLayout);
			timerGroup[i] = group;

			Label label = new Label(group, SWT.NONE);
			label.setText("On:");

			text = new Text(group, SWT.BORDER);
			text.setText("00");
			text.setTextLimit(2);
			timerInput[i * 4] = text;

			label = new Label(group, SWT.NONE);
			label.setText(":");
			text = new Text(group, SWT.BORDER);
			text.setText("00");
			text.setTextLimit(2);
			timerInput[i * 4 + 1] = text;

			label = new Label(group, SWT.NONE);
			label.setText("Off:");

			text = new Text(group, SWT.BORDER);
			text.setText("00");
			text.setTextLimit(2);
			timerInput[i * 4 + 2] = text;

			label = new Label(group, SWT.NONE);
			label.setText(":");
			text = new Text(group, SWT.BORDER);
			text.setText("00");
			text.setTextLimit(2);
			timerInput[i * 4 + 3] = text;

			GridData gd = new GridData();
			gd.horizontalSpan = 3;

			label = new Label(group, SWT.NONE);
			label.setText("Power status:");

			powerStatusInput[i] = new Button(group, SWT.CHECK);
			powerStatusInput[i].setLayoutData(gd);

			label = new Label(group, SWT.NONE);
			label.setText("Enabled:");

			timerStatusInput[i] = new Button(group, SWT.CHECK);
			timerStatusInput[i].setLayoutData(gd);

			GridData gridData = new GridData(GridData.VERTICAL_ALIGN_END);
		    gridData.horizontalSpan = 2;
		    gridData.horizontalAlignment = GridData.FILL;
		    
			Button button = new Button(group, SWT.PUSH);
			button.setText("Przelacz");
			button.setLayoutData(gridData);
			final int id = i;
			button.addSelectionListener(new SelectionListener() {

				@Override
				public void widgetSelected(SelectionEvent e) {
					try {
						Application.getComApi().switchPower(id);
					} catch (ComException e1) {
						MessageDialog.openError(getSite().getShell(),
								"Comunication errror", e1.getMessage());
					}
				}

				@Override
				public void widgetDefaultSelected(SelectionEvent e) {
					// TODO Auto-generated method stub

				}
			});
		}
	}

	/**
	 * This is a callback that will allow us to create the viewer and initialize
	 * it.
	 */
	public void createPartControl(Composite parent) {
		initView(parent);
		updateTimers();
		// Create the help context id for the viewer's control
		makeActions();
		contributeToActionBars();
		parent.redraw();
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
	}

	private void contributeToActionBars() {
		IActionBars bars = getViewSite().getActionBars();
		fillLocalToolBar(bars.getToolBarManager());
	}

	private void fillLocalToolBar(IToolBarManager manager) {
		manager.add(updateTimersAction);
	}

	private void makeActions() {
		updateTimersAction = new Action() {
			public void run() {
				try {
					transferTimers();
				} catch (ComException ex) {
					MessageDialog.openError(getSite().getShell(),
							"Comunication errror", ex.getMessage());
				}
			}
		};
		updateTimersAction.setText("Zapisz");
		updateTimersAction.setToolTipText("Zapisz");
		updateTimersAction.setImageDescriptor(PlatformUI.getWorkbench()
				.getSharedImages().getImageDescriptor(
						ISharedImages.IMG_ETOOL_SAVE_EDIT));
	}
}